﻿using System;
using System.Collections.Generic;
using System.Text;
using DocumentFormat.OpenXml;
using D = DocumentFormat.OpenXml.Drawing;
using P = DocumentFormat.OpenXml.Presentation;
using PK = DocumentFormat.OpenXml.Packaging;
using Fantom.Helper;
using Fantom.Drawing;
using Fantom.Models;
using System.Linq;

namespace Fantom.Builders
{
	/// <summary>
	/// 时间轴与动画导出模块。
	/// </summary>
	internal static class TimeLineBuilder
	{
		static TimeLineBuilder()
		{
		}

		/// <summary>
		/// 建立时间轴对象。
		/// </summary>
		/// <param name="app"></param>
		/// <param name="parent"></param>
		/// <param name="timing"></param>
		/// <param name="shapes"></param>
		/// <param name="theme"></param>
		/// <param name="mediaManager"></param>
		/// <returns></returns>
		public static ITimeLine Build(IApplication app, IFantomObject parent, P.Timing timing, IShapes shapes, Theme theme, IMediaManager mediaManager)
		{
			var timeLine = new TimeLine();
			if (timing == null) return timeLine;
			var xTimeLine = timing.TimeNodeList;
			var par = xTimeLine.GetFirstChild<P.ParallelTimeNode>();
			var ctn = par.GetFirstChild<P.CommonTimeNode>();
			var rootNodeList = ctn.GetFirstChild<P.ChildTimeNodeList>();

			// 载入所有序列。
			LoadSequences(timeLine, app, rootNodeList, shapes, theme, mediaManager);

			timeLine.Application = app;
			timeLine.Parent = parent;

			return timeLine;
		}

		// 导入并分配当前幻灯片的序列。
		private static void LoadSequences(TimeLine timeLine, IApplication app, P.ChildTimeNodeList nodeList, IShapes shapes, Theme theme, IMediaManager mediaManager)
		{
			foreach (var xseq in nodeList)
			{
				var seq = new AnimationSequence();
				LoadSequence(seq, app, timeLine, xseq as P.SequenceTimeNode, shapes, theme, mediaManager);
			}
		}

		// 载入单条序列。
		private static void LoadSequence(AnimationSequence seq, IApplication app, TimeLine timeLine, P.SequenceTimeNode xseq, IShapes shapes, Theme theme, IMediaManager mediaManager)
		{
			var ctn = xseq.GetFirstChild<P.CommonTimeNode>();

			if (ctn.NodeType.Value != P.TimeNodeValues.MainSequence)
				timeLine.InteractiveSequences.Add(seq);
			else
				timeLine.MainSequence = seq;

			LoadFragments(seq, app, ctn.GetFirstChild<P.ChildTimeNodeList>(), shapes, theme, mediaManager);

			seq.Application = app;
			seq.Parent = timeLine;

		}

		// 导入效果集合。
		private static void LoadFragments(AnimationSequence seq, IApplication app, P.ChildTimeNodeList nodeList, IShapes shapes, Theme theme, IMediaManager mediaManager)
		{
			foreach (P.ParallelTimeNode par in nodeList.ChildElements)
			{
				var fra = new AnimationFragment();
				LoadFragment(fra, app, seq, par, shapes, theme, mediaManager);
			}
		}

		// 导入效果。
		private static void LoadFragment(AnimationFragment fra, IApplication app, AnimationSequence parent, P.ParallelTimeNode par, IShapes shapes, Theme theme, IMediaManager mediaManager)
		{
			var ctn = par.GetFirstChild<P.CommonTimeNode>();

			LoadBundles(fra, app, ctn.GetFirstChild<P.ChildTimeNodeList>(), shapes, theme, mediaManager);

			fra.Application = app;
			fra.Parent = parent;
			parent.Add(fra);
		}

		// 导入动画束集合。
		private static void LoadBundles(AnimationFragment fra, IApplication app, P.ChildTimeNodeList nodeList, IShapes shapes, Theme theme, IMediaManager mediaManager)
		{
			foreach (P.ParallelTimeNode par in nodeList.ChildElements)
			{
				var bun = new AnimationBundle();
				LoadBundle(bun, app, fra, par, shapes, theme, mediaManager);
			}
		}

		// 导入动画束。
		private static void LoadBundle(AnimationBundle bun, IApplication app, AnimationFragment parent, P.ParallelTimeNode par, IShapes shapes, Theme theme, IMediaManager mediaManager)
		{
			var ctn = par.GetFirstChild<P.CommonTimeNode>();

			LoadEffects(bun, app, ctn.GetFirstChild<P.ChildTimeNodeList>(), shapes, theme, mediaManager);

			bun.Application = app;
			bun.Parent = parent;
			parent.Add(bun);
		}


		// 导入效果集合。
		private static void LoadEffects(AnimationBundle bun, IApplication app, P.ChildTimeNodeList nodeList, IShapes shapes, Theme theme, IMediaManager mediaManager)
		{
			foreach (P.ParallelTimeNode par in nodeList.ChildElements)
			{
				var eff = new AnimationEffect();
				LoadEffect(eff, app, bun, par, shapes, theme, mediaManager);
			}
		}

		// 导入效果。
		private static void LoadEffect(AnimationEffect eff, IApplication app, AnimationBundle parent, P.ParallelTimeNode par, IShapes shapes, Theme theme, IMediaManager mediaManager)
		{
			var ctn = par.GetFirstChild<P.CommonTimeNode>();

			LoadBehaviors(eff, app, ctn.GetFirstChild<P.ChildTimeNodeList>(), shapes, theme, mediaManager);

			eff.Application = app;
			eff.Parent = parent;
			parent.Add(eff);
		}

		// 导入行为集合。
		private static void LoadBehaviors(AnimationEffect eff, IApplication app, P.ChildTimeNodeList nodeList, IShapes shapes, Theme theme, IMediaManager mediaManager)
		{

			foreach (var anim in nodeList)
			{
				LoadBehavior(app, eff, anim, shapes, theme, mediaManager);
			}

		}

		private static P.ParallelTimeNode IntoPar(P.ParallelTimeNode par, int d)
		{
			var rst = par;
			for (int i = 0; i < d; i++)
			{
				rst = rst.GetFirstChild<P.CommonTimeNode>().GetFirstChild<P.ChildTimeNodeList>().GetFirstChild<P.ParallelTimeNode>();
			}
			return rst;
		}

		// 导入行为。
		private static void LoadBehavior(IApplication app, AnimationEffect parent, OpenXmlElement anim, IShapes shapes, Theme theme, IMediaManager mediaManager)
		{
			var cbhv = anim.GetFirstChild<P.CommonBehavior>();

			var bhv = Animation.BaseBehavior.LoadBehaviorFromKeyWord(anim, theme);
			var id = int.Parse(cbhv.TargetElement.ShapeTarget.ShapeId);
			bhv.Shape = shapes.FirstOrDefault((shp) => { return id == shp.Id; });
			bhv.Application = app;
			bhv.Parent = parent;
			parent.Add(bhv);
		}


		public static OpenXmlElement Export(ITimeLine model)
		{
			throw new NotImplementedException();
		}

	}
}
